package com.daoliuhe.scaffold.web.controller;

import com.daoliuhe.scaffold.model.LoginHistory;
import com.daoliuhe.scaffold.model.User;
import com.daoliuhe.scaffold.service.LoginHistoryService;
import com.daoliuhe.scaffold.service.UserService;
import com.daoliuhe.scaffold.tools.Config;
import com.daoliuhe.scaffold.tools.Constants;
import com.daoliuhe.scaffold.tools.EncryptUtil;
import com.daoliuhe.scaffold.tools.RequestUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.util.SavedRequest;
import org.apache.shiro.web.util.WebUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.math.BigDecimal;
import java.util.Calendar;

@Controller
@RequestMapping("/login")
public class LoginController {

    private static final Logger logger = LoggerFactory.getLogger(LoginController.class);

    @Resource
    UserService userService;

    @Autowired
    LoginHistoryService loginHistoryService;

    /**
     * 登录
     *
     * @param request
     * @return
     */
    @GetMapping
    public String login(HttpServletRequest request) {
        logger.info("login()");
        Subject currentUser = SecurityUtils.getSubject();
        ModelAndView mav = new ModelAndView();
        //是否记住我
        boolean isRemembered = currentUser.isRemembered();
        boolean forceLogout = false;
        String status = "";
        if (request.getParameter("forceLogout") != null) {
            status = "您已经被管理员强制退出，请重新登录";
            forceLogout = true;
        }
        //记住登录，并且没有被强制退出,转到登录页面
        if (isRemembered && !forceLogout) {
            mav.setViewName("forward:/login/doLogin");
        } else {
            //跳转登录页面
            mav.setViewName("login");
            mav.addObject("status", status);
        }
        return "login";
    }

    /**
     * 登录
     *
     * @param session
     * @param user
     * @return
     */
    @RequestMapping("/doLogin")
    public ModelAndView doLogin(HttpSession session, User user, HttpServletRequest request, HttpServletResponse response) {
        logger.info("doLogin(),user:{}", user);
        ModelAndView mav = new ModelAndView();
        String status = "";
        Subject currentUser = SecurityUtils.getSubject();
        //是否记住我
        //boolean isRemembered = currentUser.isRemembered();
        // 判断用户是否处于登录状态
        if (!currentUser.isAuthenticated()) {
            UsernamePasswordToken token = new UsernamePasswordToken(user.getLoginId(), user.getUserPassword());
            token.setRememberMe(user.isRememberMe());
            try {
                currentUser.login(token);
                //保存账号密码到cookie中
                if (user.isRememberMe()) {
                    String enUsername = EncryptUtil.encode(user.getLoginId());
                    String enPassword = EncryptUtil.encode(user.getUserPassword());
                    RequestUtils.setCookie(request, response, Constants.COOKIE_USER_NAME, enUsername, Config.COOKIE_MAXAGE);
                    RequestUtils.setCookie(request, response, Constants.COOKIE_PASSWORD, enPassword, Config.COOKIE_MAXAGE);
                }
            } catch (UnknownAccountException uae) {
                uae.printStackTrace();
                logger.error("doLogin(),,user:{},UnknownAccountException uae.getMessage:{},uae.getLocalizedMessage:{}, uae.getStackTrace :{}",
                        user, uae.getMessage(), uae.getLocalizedMessage(), uae.getStackTrace());
                status = "用户名不正确!";
            } catch (IncorrectCredentialsException ice) {
                ice.printStackTrace();
                logger.error("doLogin(),,user:{},IncorrectCredentialsException ice.getMessage:{},ice.getLocalizedMessage:{}, ice.getStackTrace :{}",
                        user, ice.getMessage(), ice.getLocalizedMessage(), ice.getStackTrace());
                status = "密码不正确！";
            } catch (LockedAccountException lae) {
                lae.printStackTrace();
                logger.error("doLogin(),,user:{},LockedAccountException lae.getMessage:{},lae.getLocalizedMessage:{}, lae.getStackTrace :{}",
                        user, lae.getMessage(), lae.getLocalizedMessage(), lae.getStackTrace());
                status = "用户已被禁用！";
            } catch (AuthenticationException ae) {
                ae.printStackTrace();
                logger.error("doLogin(),,user:{},AuthenticationException ae.getMessage:{},ae.getLocalizedMessage:{}, ae.getStackTrace :{}",
                        user, ae.getMessage(), ae.getLocalizedMessage(), ae.getStackTrace());
                status = "无法登录!";
            }
        }

        boolean isAuth = currentUser.isAuthenticated();
        if (isAuth) {
            User loginUser = userService.getUserByLoginId(user.getLoginId());
            //查找到用户，并且当前用户的状态为启用
            if (null != loginUser && Constants.ENABLE.equalsIgnoreCase(loginUser.getEnabled())) {
                //设置客户端ip
                String ip = request.getHeader("x-forwarded-for");
                session.setAttribute(Constants.USER_IP, ip);
                session.setAttribute(Constants.USERINFO, loginUser);
                SavedRequest savedRequest = WebUtils.getSavedRequest(request);
                logger.info("doLogin(),savedRequest:{}", savedRequest);
                if (null == savedRequest) {
                    mav.setViewName("redirect:/main");
                } else {
                    String redirect = savedRequest.getRequestUrl().replace("/", "");
                    logger.info("doLogin(),redirect:{}", redirect);
                    if (StringUtils.isEmpty(redirect) || "/".equalsIgnoreCase(redirect)) {
                        mav.setViewName("redirect:/main");
                    } else {
                        mav.setViewName("redirect:" + redirect);
                    }
                }
                //保存登录记录
                LoginHistory history = new LoginHistory();
                history.setUserId(new BigDecimal(loginUser.getId()));
                if (StringUtils.isEmpty(ip)) {
                    history.setAddress(currentUser.getSession().getHost());
                } else {
                    history.setAddress(ip);
                }
                history.setType(Constants.TYPE_LOGIN);
                loginHistoryService.saveHistory(history);
            } else {
                status = "用户已被禁用或没有同步到系统中！";
                logger.info("doLogin(),status:{}", status);
                mav.setViewName("login");
                Calendar c = Calendar.getInstance();
                int year = c.get(Calendar.YEAR);
                mav.addObject("status", status);
                mav.addObject("year", year);
            }
        } else {
            logger.info("doLogin(),status:{}", status);
            mav.setViewName("login");
            Calendar c = Calendar.getInstance();
            int year = c.get(Calendar.YEAR);
            mav.addObject("status", status);
            mav.addObject("year", year);
        }
        return mav;
    }

    /**
     * 登出
     *
     * @return
     */
    @RequestMapping("/logout")
    public ModelAndView logout(HttpSession session, HttpServletRequest request, HttpServletResponse response) {
        logger.info("logout");
        ModelAndView mav = new ModelAndView();
        mav.setViewName("login");
        Subject subject = SecurityUtils.getSubject();
        //保存登录记录
        if (subject.isAuthenticated()) {
            User user = (User) session.getAttribute(Constants.USERINFO);
            String ip = (String) session.getAttribute(Constants.USER_IP);
            if (StringUtils.isEmpty(ip)) {
                ip = subject.getSession().getHost();
            }
            if (null != user) {
                LoginHistory history = new LoginHistory();
                history.setUserId(new BigDecimal(user.getId()));
                history.setAddress(ip);
                history.setType(Constants.TYPE_LOGOUT);
                loginHistoryService.saveHistory(history);
            }
        }
        session.removeAttribute(Constants.USERINFO);
        subject.logout();
        //删除保存的cookie
        RequestUtils.deleteCookie(request, response, Constants.COOKIE_USER_NAME, true);
        RequestUtils.deleteCookie(request, response, Constants.COOKIE_PASSWORD, true);
        Calendar c = Calendar.getInstance();
        int year = c.get(Calendar.YEAR);
        mav.addObject("year", year);
        return mav;

    }

    /**
     * 没有权限的页面
     *
     * @return
     */
    @RequestMapping("/unauthorized")
    public ModelAndView unauthorized() {
        logger.info("unauthorized()");
        ModelAndView mav = new ModelAndView();
        mav.setViewName("unauthorized");
        return mav;

    }

}
